/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package rules;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import types.ColoringInfo;
import types.ISudokuMatrix;
import utils.RuleHelper;
import types.ISudokuMatrix;

/**
 *
 * @author ali
 */
public class ColumnThreeFree implements Rule {

    int quadrat = 0;

    Collection checkedBlocks = new HashSet();
    Collection checkedCols = new HashSet();
    Collection checkedRows =new HashSet();

    public String getName() {
        return ColumnThreeFree.class.getSimpleName();
    }

    public String getPicName() {
        return "Betrachte die anderen leeren Felder in der Spalte und \nversuche die Kandidaten solange auszuschlißen, bis" +
                "nur eine Kandidat übrig ist" ;
    }

    public boolean isApplicable(int x, int y, ISudokuMatrix matrix) {
        System.out.println("Trying to apply rule "+ this.getName()+ " for "+x+","+y);
        try {

            this.setQuadrat(x, y);
            int[] digits = RuleHelper.getDigistsSameCol(y, matrix);

            Collection missedDigits = RuleHelper.getMissingdigitsInQuadratOrColOrRow(RuleHelper.intArrayToCollection(digits));

            this.checkedCols.add(y);

            System.out.print("missed digits in Col " + y + ": ");
            RuleHelper.printCollection(missedDigits);


            if (missedDigits.size() > 3) {
                return false;
            }

            Collection candidates = RuleHelper.cloneCollection(missedDigits);

            Iterator iter = missedDigits.iterator();
            while (iter.hasNext()) {
                Integer digit = (Integer) iter.next();

                if (RuleHelper.existsDigitInRow(digit, x, matrix) || RuleHelper.existsDigitInQuadrat(digit, x, y, matrix)) {
                    candidates.remove(digit);
                    System.out.println( "\n"+digit + " exists in Row " + x + " and/or in Quadrat: " + RuleHelper.calculateQuadratNumber(x, y));
                    System.out.println(digit+" can be exculuded." );
                }

                if(RuleHelper.existsDigitInRow(digit, x, matrix))
                {
                    this.checkedRows.add(x);
                }

                if(RuleHelper.existsDigitInQuadrat(digit, x, y, matrix))
                {
                    this.checkedBlocks.add(RuleHelper.calculateQuadratNumber(x, y));

                }

            }

            //2 zahlen konnten asugeschloßen werden--> true
            if (candidates.size()==1)
            {
                System.out.println("Rule applicable");
                return true;
            }


            missedDigits = RuleHelper.cloneCollection(candidates);
            System.out.print("Candidates:");
            RuleHelper.printCollection(candidates);

            Iterator iter1 = candidates.iterator();
            while (iter1.hasNext()) {
                int counter = 0;
                Integer a = (Integer) iter1.next();
                System.out.println("\nVersuch " + a + " bei anderen Felder auszuschließen. ");

                for (int i = 0; i < digits.length; i++) {
                    //ignoriere leere Zeilen + den leeren feld selbst
                    if (digits[i] != 0 || i == x) {
                        continue;
                    }

                    if (RuleHelper.existsDigitInRow(a, i, matrix) || RuleHelper.existsDigitInQuadrat(a, i, y, matrix)) {
                        System.out.println("\n" + a + " exists in Row " + i + " and/or in Quadrat: " + RuleHelper.calculateQuadratNumber(i, y));
                        counter++;

                    }

                    if(RuleHelper.existsDigitInRow(a, i, matrix))
                    {
                       this.checkedRows.add(i);
                    }

                    if(RuleHelper.existsDigitInQuadrat(a, i, y, matrix))
                    {
                      this.checkedBlocks.add(RuleHelper.calculateQuadratNumber(i, y));

                    }


                }
                if (counter == 2) {
                    {
                        missedDigits.remove(a);
                        System.out.println(a+" can be exculuded." ); 
                        
                    }
                }
            }
             if (missedDigits.size()<=1)
             {
                 System.out.println("Rule applicable");
                 return true;
             }
            
        } catch (Exception ex) {
            Logger.getLogger(ColumnTwoFree.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;

    }

    public int getWeight(int QuadratNumber) {

        //5 für spalte selbst +
        //15 für drei zeilen oder drei Quadraten
        if (QuadratNumber==4 || QuadratNumber==5 || QuadratNumber==6)
        {
            return (5+15)*2;
        }
        else
            //6 für spalte selbst +
            //15 für drei zeilen oder drei Quadraten
            return (15+6)* 2;
        }

    public int compareTo(Rule o) {
        if (this.getWeight(this.getQuadrat())<o.getWeight(o.getQuadrat()))
            return -1;
        else if (this.getWeight(this.getQuadrat())>o.getWeight(o.getQuadrat()))
            return 1;
        else
            return 0;
    }

    public void setQuadrat(int x, int y) throws Exception {

            this.quadrat = RuleHelper.calculateQuadratNumber(x, y);

    }

    public int getQuadrat() {
       return this.quadrat;
    }

    public ColoringInfo getCheckedUnits(int x, int y, ISudokuMatrix matrix) {

        ColoringInfo ci = new ColoringInfo();

        ci.setBlocks(this.checkedBlocks);
        ci.setColums(this.checkedCols);
        ci.setRows(this.checkedRows);

        return ci;

    }
}
